package com.tmpt.service.impl;

import com.googlecode.genericdao.search.Search;
import com.inspiresoftware.lib.dto.geda.assembler.DTOAssembler;
import com.tmpt.beans.A2Company;
import com.tmpt.beans.A2LowUserTmp;
import com.tmpt.beans.A2Post;
import com.tmpt.beans.A2User;
import com.tmpt.dao.intf.IA2CompanyDao;
import com.tmpt.dao.intf.IA2LowUserTmpDao;
import com.tmpt.dao.intf.IA2PostDao;
import com.tmpt.dao.intf.IA2UserDao;
import com.tmpt.dto.A2PostDto;
import com.tmpt.dto.A2UserDto;
import com.tmpt.dto.Result;
import com.tmpt.service.IOperationlogService;
import com.tmpt.service.IOrgService;
import com.tmptSource.dto.A2userDto;
import com.tmptSource.dto.OwSigninDto;
import org.apache.log4j.Logger;
import org.dozer.Mapper;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Transactional(propagation=Propagation.REQUIRED)
public class OrgService implements IOrgService {
	@Resource IA2CompanyDao a2CompanyDao;
	@Resource IA2UserDao a2UserDao;
	@Resource IA2PostDao a2PostDao;
	@Resource IA2LowUserTmpDao a2LowUserTmpDao;
	@Autowired
	private Mapper mapper;

	@Resource
	private IOperationlogService operationlogService;

	private Logger log = Logger.getLogger(this.getClass());




	@Override
	public Result<A2PostDto> addPost(A2PostDto postDto, long parentPostId, long companyId){
		Result result = new Result();

		A2Post post = new A2Post();
		DTOAssembler dtoAssembler = DTOAssembler.newAssembler(A2PostDto.class);
		dtoAssembler.assembleEntity(postDto, post, null, null);

		//找上级岗位
		A2Post parentPost = null;
		if(parentPostId!=0){
			parentPost = a2PostDao.fetch(parentPostId);
		}
		//查所属公司
		A2Company company = a2CompanyDao.fetch(companyId);
		//添加数据
		post.setA2Company(company);
		post.setA2Post(parentPost);
		a2PostDao.create(post);

		return result.success();
	}

	@Override
	public Result<A2PostDto> queryPostById(long id) {
		Result<A2PostDto> result = new Result();

		A2Post post = a2PostDao.fetch(id);
		A2PostDto postDto = new A2PostDto();
		DTOAssembler dtoAssembler = DTOAssembler.newAssembler(A2PostDto.class);
		dtoAssembler.assembleDto(postDto, post, null, null);
		result.setResultObj(postDto);

		return result.success();
	}

	@Override
	public Result<A2PostDto> modifyPostById(A2PostDto postDto) {
		Result<A2PostDto> result = new Result();

		A2Post post = a2PostDao.fetch(postDto.getId());
		post.setName(postDto.getName());
		a2PostDao.update(post);

		return result.success();
	}

	@Override
	public Result<A2PostDto> removePostById(long id) {
		Result<A2PostDto> result = new Result();

		A2Post post = a2PostDao.fetch(id);
		post.setDeleteFlag(1);
		a2PostDao.update(post);

		return result.success();
	}

	@Override
	public Result<A2PostDto> queryPostJsonTreeByCompanyId(long companyId) {
		Result<A2PostDto> result = new Result();

		A2Company company = a2CompanyDao.fetch(companyId);
		String companyName = company.getName();

		Search search = new Search();
		search.addFilterEqual("a2Company.id",companyId);
		search.addFilterEqual("deleteFlag", 0);
		search.addFilterEmpty("a2Post");
		List<A2Post> postList = a2PostDao.search(search);

		//解析
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("id","cId-"+companyId);
		jsonObject.put("companyId", companyId);
		jsonObject.put("text", companyName);
		jsonObject.put("name", companyName);
		jsonObject.put("state", "opened");

		//map
		Map map = new HashMap<>();
		map.put("id","cId-"+companyId);
		map.put("companyId",companyId);
		map.put("type",0);
		map.put("text", companyName);
		map.put("name", companyName);
		map.put("state", "opened");

		//递归生成树
		genPostJsonTree(jsonObject,map, postList,companyId);

		JSONArray jsonArray = new JSONArray();
		jsonArray.put(jsonObject);
		String jsonArrayStr = jsonArray.toString();

		List list = new ArrayList<>();
		list.add(map);

		//.out.println("list"+list);
		result.getResultMap().put("list", list);
		result.getResultMap().put("jsonArrayStr",jsonArrayStr);
		return result.success();
	}

	/**
	 * 递归Post生成树
	 */
	private void genPostJsonTree(JSONObject jsonObject,Map map,List<A2Post> postList, long companyId){
		JSONArray jsonArray = new JSONArray();
		List list = new ArrayList<>();

		jsonObject.put("children",jsonArray);
		map.put("children",list);
		for(A2Post post: postList){
			long id = post.getId();
			int deleteFlag = post.getDeleteFlag();
			if(deleteFlag==1){
				continue;
			}
			String name = post.getName();

			//json
			JSONObject jsonObjectSon = new JSONObject();
			jsonObjectSon.put("id",id);
			jsonObjectSon.put("text",name);
			jsonObjectSon.put("name",name);
			//jsonObjectSon.put("state","opened");
			//jsonObjectSon.put("state","closed");
			jsonArray.put(jsonObjectSon);

			//map
			Map mapSon = new HashMap<>();
			mapSon.put("id",id);
			mapSon.put("companyId",companyId);
			mapSon.put("type",1);
			mapSon.put("text",name);
			mapSon.put("name",name);
			list.add(mapSon);

			List<A2Post> postSonList = post.getA2PostList();
			if(postSonList.size()==0){continue;}
			genPostJsonTree(jsonObjectSon,mapSon,postSonList,companyId);
		}
	}

	private Lock _lock = new ReentrantLock();// 锁对象

	/**
	 * 初始化下指定员工的下属员工及岗位内员工
	 * userType:员工类型:1,下属员工; 2,同岗位同级员工
	 * @param userId
	 * @return
	 */
	@Override
	public Result initPostUser(long userId){
		try{
			_lock.lock();

			Result result = new Result();

			//先清空用户数据
			clearSonPostUser(userId);

			A2User user = a2UserDao.fetch(userId);
			A2Post post = user.getA2Post();
			//取下属岗位
			if(post.getDeleteFlag()==1) {return result.success();}
			List<A2Post> allPostSonList = new ArrayList<>();
			getSonPost(post,allPostSonList);
			//下属岗位user
			for (A2Post postLow : allPostSonList) {
				////.out.println(postLow.getId() + "-" + postLow.getName());
				for(A2User a2User: postLow.getA2UserList()){
					long userIdLowPost = a2User.getId();
					A2LowUserTmp lowUserTmp = new A2LowUserTmp();
					lowUserTmp.setUserId(userId);
					lowUserTmp.setUserType(1);
					lowUserTmp.setLowUserId(userIdLowPost);
					a2LowUserTmpDao.create(lowUserTmp);
				}
			}
			//同岗位user
			List<A2User> userList = post.getA2UserList();
			for(A2User a2User: userList){
				long userIdSamePost = a2User.getId();
				A2LowUserTmp lowUserTmp = new A2LowUserTmp();
				lowUserTmp.setUserId(userId);
				if(userIdSamePost == userId){//本人：设置成本人的下级，这样在查看本人下级时，自己的记录也会出来
					lowUserTmp.setUserType(1);
				}else{
					lowUserTmp.setUserType(2);
				}
				lowUserTmp.setLowUserId(userIdSamePost);
				a2LowUserTmpDao.create(lowUserTmp);
			}
			return result.success();

		}finally {
			_lock.unlock();
		}

	}

	private void clearSonPostUser(long userId){
		Search search = new Search();
		search.addFilterEqual("userId", userId);
		List<A2LowUserTmp> a2LowUserTmpList = a2LowUserTmpDao.search(search);
		for(A2LowUserTmp a2LowUserTmp:a2LowUserTmpList){
			a2LowUserTmpDao.deleteEntity(a2LowUserTmp);
		}
	}

	/**
	 * 取下属岗位
	 * @param post
	 * @param allPostSonList 存放下级岗位
	 * @return
	 */
	private void getSonPost(A2Post post,List<A2Post> allPostSonList){
		List<A2Post> postList = post.getA2PostList();
		for(A2Post postSon:postList){
			if(post.getDeleteFlag()==1) {continue;}
			allPostSonList.add(postSon);
			getSonPost(postSon, allPostSonList);
		}
	}


	/**
	 * 取下属员工信息
	 * @param userId
	 * @return
	 */
	@Override
	public Result queryLowPostUsersByUser(long userId){
		Result result = new Result();

		List<A2userDto> list = new ArrayList<>();
		Search search = new Search();
		search.addFilterEqual("userId", userId);
		search.addFilterEqual("userType", 1);
		List<A2LowUserTmp> a2LowUserTmpList = a2LowUserTmpDao.search(search);
		for(A2LowUserTmp a2LowUserTmp : a2LowUserTmpList){
			long lowUserId = a2LowUserTmp.getLowUserId();
			if(lowUserId == userId)continue;//下属是自己，不用显示了。下属是自己放入表里，主要是查询时要用
			search.clear();
			search.addFilterEqual("id",lowUserId);
			A2User a2User = (A2User)a2UserDao.searchUnique(search);
			A2userDto a2userDto = mapper.map(a2User,A2userDto.class);
			String a2postName = "";
			if(a2User.getA2Post()!=null){
				a2postName = a2User.getA2Post().getName();
			}
			a2userDto.setA2postName(a2postName);
			list.add(a2userDto);
		}

		result.getResultMap().put("rows",list);
		result.getResultMap().put("total",list.size());

		return result.success();
	}


}

